前面介紹的前後端分離架構,Backend 仍然只有一台 Server。
例如:
Browser
│
▼
Frontend
│
▼
Backend Server
│
▼
Database
如果使用者數量增加,所有 API Request 都集中在同一台 Backend Server 上,就可能開始出現問題。
例如:
此時就可以把 Backend 從一台增加成多台。
Backend 1
Backend 2
Backend 3
但新的問題是:
Browser 到底要把 Request 傳給哪一台 Backend?
這就是 Load Balancer 要處理的事情。
Load Balancer 中文通常稱為「負載平衡器」。
它會位於使用者與多台 Backend Server 之間,負責接收 Request,再將 Request 分配到不同 Server。
架構可以簡化為:
Browser
│
▼
Load Balancer
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
Backend 1 Backend 2 Backend 3
對 Browser 而言,它不需要知道後面到底有幾台 Backend。
Browser 只需要呼叫:
https://api.example.com
真正的 Server 分配工作由 Load Balancer 負責。
例如:
Request 1 → Backend 1
Request 2 → Backend 2
Request 3 → Backend 3
Request 4 → Backend 1
因此 Load Balancer 就像一個流量入口。
最直接的原因是讓系統可以做「水平擴充」。
原本只有:
Backend Server
CPU 80%
Memory 85%
如果單純升級這台機器:
4 Core → 8 Core
8 GB RAM → 16 GB RAM
這稱為:
Vertical Scaling(垂直擴充)
也就是把同一台 Server 變得更強。
另一種方式則是增加機器:
Backend 1
Backend 2
Backend 3
這稱為:
Horizontal Scaling(水平擴充)
Load Balancer 就是水平擴充時非常重要的一環。
假設目前 Backend 有三台:
Backend 1: 10.0.0.11:8000
Backend 2: 10.0.0.12:8000
Backend 3: 10.0.0.13:8000
使用者呼叫:
GET https://api.example.com/products
Request 不會直接進到某一台 FastAPI,而是先到 Load Balancer。
Browser
│
│ GET /products
▼
Load Balancer
│
▼
Backend 2
│
▼
FastAPI
│
▼
Database
FastAPI 處理完成後回傳 JSON:
{
"data": [
{
"id": 1,
"name": "Product A"
}
]
}
Response 再沿原路回去:
Database
│
▼
FastAPI
│
▼
Load Balancer
│
▼
Browser
因此 Load Balancer 的完整角色就是:
Client Request
│
▼
Load Balancer
│
├── Backend 1
├── Backend 2
└── Backend 3
最常見的方法之一叫做:
Round Robin
也就是輪流分配。
例如:
Request 1 → Backend 1
Request 2 → Backend 2
Request 3 → Backend 3
Request 4 → Backend 1
Request 5 → Backend 2
如果三台機器效能差不多,這是一個很直覺的方式。
另外還有其他策略。
例如:
Least Connections
把新的 Request 分配給目前連線數最少的 Server。
Backend 1 → 100 connections
Backend 2 → 40 connections
Backend 3 → 70 connections
New Request
│
▼
Backend 2
因為 Backend 2 目前比較空閒。
另外還可能使用:
不同策略適合不同場景。
Nginx 不只是 Reverse Proxy,也可以直接做到 Load Balancing。
例如:
upstream backend_servers {
server 10.0.0.11:8000;
server 10.0.0.12:8000;
server 10.0.0.13:8000;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend_servers;
}
}
其中:
upstream backend_servers
就是定義一組 Backend Server。
10.0.0.11:8000
10.0.0.12:8000
10.0.0.13:8000
當 Request 進來:
api.example.com/products
Nginx 就會從這三台 Server 中選一台處理。
整個架構就是:
Internet
│
▼
Nginx Load Balancer
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
FastAPI 1 FastAPI 2 FastAPI 3
假設沒有 Load Balancer,只有一台 Backend:
Browser
│
▼
Backend Server
如果 Backend Server 掛掉:
Backend Server
X
整個 API 就無法使用。
但如果有三台:
Load Balancer
/ | \
▼ ▼ ▼
API 1 API 2 API 3
就算其中一台故障:
API 1 ✓
API 2 X
API 3 ✓
Load Balancer 可以停止把 Request 傳給 API 2。
流量仍然可以送到:
API 1
API 3
因此系統不一定會完全中斷。
這就是 Load Balancer 在「高可用性」上的另一個重要作用。
Load Balancer 必須知道 Backend 還活著,否則它可能一直把 Request 傳給已經掛掉的機器。
因此通常會設定:
Health Check
例如每隔一段時間檢查:
GET /health
FastAPI 可以提供:
@app.get("/health")
def health_check():
return {
"status": "ok"
}
如果 Server 正常:
200 OK
Load Balancer 就繼續送流量。
如果 Server 一直回:
500
或根本無法連線,Load Balancer 就可以暫時把這台 Server 移出流量池。
概念上就是:
Backend 1 → Healthy
Backend 2 → Unhealthy
Backend 3 → Healthy
因此:
Request
│
▼
Load Balancer
├── Backend 1 ✓
├── Backend 2 X
└── Backend 3 ✓
前後端分離再加入 Load Balancer,可以變成:
User
│
▼
Internet
│
┌───────────┴───────────┐
│ │
▼ ▼
www.example.com api.example.com
│ │
▼ ▼
Frontend Server Load Balancer
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
API 1 API 2 API 3
\ │ /
\ │ /
└───────┼───────┘
│
▼
Database
這時候各層的責任就會變得很清楚:
Frontend
→ 顯示畫面
Load Balancer
→ 分配 API 流量
Backend
→ 處理商業邏輯
Database
→ 保存資料
Backend 從一台變成多台之後,雖然解決了效能與單點故障問題,但也會產生新的問題。
例如:
使用者登入
│
▼
Request 1 → Backend 1
假設 Backend 1 把登入狀態存在自己的記憶體裡。
下一個 Request:
Request 2 → Backend 2
Backend 2 並不知道使用者剛才已經登入。
這就會出現問題。
因此多台 Backend 架構通常不能把重要 Session 狀態只存在單一 Backend 的 Memory。
常見做法是把共享狀態放到:
Redis
Database
例如:
Load Balancer
│
┌─────────┴─────────┐
│ │
▼ ▼
Backend 1 Backend 2
│ │
└─────────┬─────────┘
│
▼
Redis
這樣不管 Request 被分配到哪一台 Backend,都可以取得相同的登入 Session 或 Cache 資料。
因此從一台 Backend 擴充到多台 Backend 之後,系統架構往往也會開始加入 Redis、共享儲存與集中式資料庫等元件。
到這裡,整個部署架構可以整理成:
第一階段:單機部署
Nginx
├── Frontend
├── Backend
└── Database
接著:
第二階段:前後端分離
Frontend Server
Backend Server
│
▼
Database
再往後:
第三階段:Load Balancer
Frontend
│
▼
Load Balancer
│
┌──┼──┐
▼ ▼ ▼
API API API
│
▼
Database
如果系統再繼續成長,就會逐漸遇到更多部署問題,例如:
Redis
Docker
CI/CD
Container Registry
Auto Scaling
Kubernetes
Cloud Load Balancer
因此 Load Balancer 可以視為從「單機部署」走向「分散式系統」的一個重要分水嶺。